//********************************************************************
// 
//  file:  FileManagement.cs
//  File Management Implementation for Diomede Storage Service
//
//  (C) Copyright 2010, Diomede Corporation
//  All rights reserved
// 
//  Use, modification, and distribution is subject to   
//  the New BSD License (See accompanying file license.txt).
// 
//********************************************************************

using System;
using System.Collections.Generic;
using System.IO;
using data.diomedestorage.com;

using Diomede.SDK.Enums;

namespace Diomede.SDK
{

    #region Main Interface

    /// <summary>
    /// Provide interface for handling files in Diomede Storage.
    /// </summary>
    /// <example>
    /// <code>
    /// void uploadFile(string fileToUpload)
    /// {
    ///     //create new session
    ///     ISession session = new Session();
    /// 
    ///     if (session.Login("username", "password").Status != Diomede.SDK.Enums.ExecutionResults.Success)
    ///     {
    ///         Console.WriteLine("Fail to login to Diomede Service.");
    ///         return;
    ///     }
    /// 
    ///     IFileManagement fileMgr = session as IFileManagement;
    ///     //add Progress event handler
    ///     fileMgr.OnFileUploadProgress += new EventHandler&lt;FileUploadProgressArgs&gt;(fileMgr_OnFileUploadProgress);
    ///     Utils.WriteMessage(string.Format("Starting to upload {0}..", fileToUpload));
    ///     //upload file now
    ///     IFileManagementExecResult result = fileMgr.Upload(fileToUpload, Diomede.SDK.Enums.StorageTiers.OnlineStorage);
    ///     if (result.Status == Enums.ExecutionResults.Success)
    ///     {
    ///         Console.WriteLine("Upload successful... Press any key");
    ///         Console.ReadKey();
    ///     }
    /// 
    /// }
    /// 
    /// void fileMgr_OnFileUploadProgress(object sender, FileUploadProgressArgs e)
    /// {
    ///     Console.WriteLine(string.Format("Upload progress... {0} / {1}", e.ToProgressString(), e.ToPercentString()));
    /// }
    /// </code>
    /// <code lang="VB.NET">
    /// Sub UploadFile(ByVal filePath As String)
    ///     'create new session
    ///     Dim session As ISession = New Session()
    ///     If Not (session.Login("username", "password").Status = Enums.ExecutionResults.Success) Then
    ///         Console.WriteLine("Failed to login to Diomede Service.")
    ///         Return
    ///     End If
    /// 
    ///     dim fileMgr as IFileManagement = session
    ///     'add event handler
    ///     AddHandler fileMgr.OnFileUploadProgress, AddressOf fileMgr_OnFileUploadProgress
    /// 
    ///     Dim result As IFileManagementExecResult = fileMgr.Upload(filePath, Enums.StorageTiers.OnlineStorage)
    ///     If (result.Status = Enums.ExecutionResults.Success) Then
    ///         Console.WriteLine("Upload successful...")
    ///     Else
    ///         Console.WriteLine(String.Format("Fail to upload file, error: {0}.", result.Message))
    ///     End If
    /// End Sub
    /// 
    /// Sub fileMgr_OnFileUploadProgress(ByVal sender As Object, ByVal e As FileUploadProgressArgs)
    ///     Console.WriteLine(String.Format("Upload progress... {0} / {1}", e.ToProgressString(), e.ToPercentString()))
    /// End Sub
    /// 
    /// </code>
    /// </example>
    public interface IFileManagement
    {
        #region Searching

        IFileManagementExecResult SearchFiles(System.Nullable<long> fileID, string fileName, string hashMD5, string hashSHA1, System.Nullable<long> minSize, System.Nullable<long> maxSize, System.Nullable<System.DateTime> dateStart, System.Nullable<System.DateTime> dateEnd, System.Nullable<bool> isDeleted, System.Nullable<bool> isComplete, string metaName, string metaValue, long offset, long pageSize);

        ISearchFilesSummaryResult SearchFilesSummary(System.Nullable<long> fileID, string fileName, string hashMD5, string hashSHA1, System.Nullable<long> minSize, System.Nullable<long> maxSize, System.Nullable<System.DateTime> dateStart, System.Nullable<System.DateTime> dateEnd, System.Nullable<bool> isDeleted, System.Nullable<bool> displayIncompleteFiles, string metaName, string metaValue);

        ISearchUploadLogsExecResult SearchUploadLogs(long? fileID, DateTime? startDate, DateTime? endDate, string ip, long offset, long pageSize);

        #endregion

        #region File Uploading

        IGetUploadTokenExecResult GetUploadToken(string fileName, string callback);

        ICreateFileExecResult CreateFile(string fileName);

        ICreateFileExecResult CreateFile(string fileName, string encoding, string callbackAddress);

        IUploadExecResult Upload(string fileName);

        IUploadExecResult Upload(string fileName, string encoding, string callback);

        IUploadExecResult Upload(string fileName, long offset, long length);

        IUploadExecResult Upload(string fileName, long offset, long length, string encoding, string callbackAddress);

        IUploadExecResult Upload(long fileID, Stream stream, long offset, bool isComplete);

        IUploadExecResult Upload(long fileID, Stream stream, long offset, bool isComplete, string encoding, string callbackAddress);

        #endregion

        #region Dialogs
        ///// <summary>
        ///// Use to upload file to Diomede storage, using <see cref="System.IO.FileInfo"/> as parameter.
        ///// </summary>
        ///// <param name="file">File to upload</param>
        ///// 
        ///// <returns>Will return File Management Execution result, see <see cref="IFileManagementExecResult"/> for more information.</returns>
        ///// <example>
        ///// <code>
        ///// void uploadFile(string fileToUpload)
        ///// {
        /////     //create new session
        /////     ISession session = new Session();
        ///// 
        /////     if (session.Login("username", "password").Status != Diomede.SDK.Enums.ExecutionResults.Success)
        /////     {
        /////         Console.WriteLine("Fail to login to Diomede Service.");
        /////         return;
        /////     }
        ///// 
        /////     IFileManagement fileMgr = session as IFileManagement;
        /////     //add Progress event handler
        /////     fileMgr.OnFileUploadProgress += new EventHandler&lt;FileUploadProgressArgs&gt;(fileMgr_OnFileUploadProgress);
        /////     Utils.WriteMessage(string.Format("Starting to upload {0}..", fileToUpload));
        /////     //upload file now
        /////     IFileManagementExecResult result = fileMgr.Upload(fileToUpload, Diomede.SDK.Enums.StorageTiers.OnlineStorage);
        /////     if (result.Status == Enums.ExecutionResults.Success)
        /////     {
        /////         Console.WriteLine("Upload successful... Press any key");
        /////         Console.ReadKey();
        /////     }
        ///// 
        ///// }
        ///// 
        ///// void fileMgr_OnFileUploadProgress(object sender, FileUploadProgressArgs e)
        ///// {
        /////     Console.WriteLine(string.Format("Upload progress... {0} / {1}", e.ToProgressString(), e.ToPercentString()));
        ///// }
        ///// </code>
        ///// <code lang="VB.NET">
        ///// Sub UploadFile(ByVal filePath As String)
        /////     'create new session
        /////     Dim session As ISession = New Session()
        /////     If Not (session.Login("username", "password").Status = Enums.ExecutionResults.Success) Then
        /////         Console.WriteLine("Failed to login to Diomede Service.")
        /////         Return
        /////     End If
        ///// 
        /////     dim fileMgr as IFileManagement = session
        /////     'add event handler
        /////     AddHandler fileMgr.OnFileUploadProgress, AddressOf fileMgr_OnFileUploadProgress
        ///// 
        /////     Dim result As IFileManagementExecResult = fileMgr.Upload(filePath, Enums.StorageTiers.OnlineStorage)
        /////     If (result.Status = Enums.ExecutionResults.Success) Then
        /////         Console.WriteLine("Upload successful...")
        /////     Else
        /////         Console.WriteLine(String.Format("Fail to upload file, error: {0}.", result.Message))
        /////     End If
        ///// End Sub
        ///// 
        ///// Sub fileMgr_OnFileUploadProgress(ByVal sender As Object, ByVal e As FileUploadProgressArgs)
        /////     Console.WriteLine(String.Format("Upload progress... {0} / {1}", e.ToProgressString(), e.ToPercentString()))
        ///// End Sub
        ///// 
        ///// </code>
        ///// </example>
        //IFileManagementExecResult Upload(FileInfo file);
        //
        ///// <summary>
        ///// Use to upload file to Diomede storage.
        ///// </summary>
        ///// <param name="file">File Info.</param>
        ///// 
        ///// <param name="contentEncoding">Content Encoding.</param>
        ///// <param name="callbackAddress">Call Back Address.</param>
        ///// <returns>Will return File Management Execution result, see <see cref="IFileManagementExecResult"/> for more information.</returns>
        //IFileManagementExecResult Upload(FileInfo file, string contentEncoding, string callbackAddress);

        //IFileManagementExecResult Upload(FileInfo file, string contentEncoding, string callbackAddress, long? FileID);

        ///// <summary>
        ///// Retrieves the Upload Resume information of a file.
        ///// </summary>
        ///// <param name="fileMD5Hash">MD5 Hash.</param>
        ///// <returns>Will return File Management Execution result, see <see cref="IFileManagementExecResult"/> for more information.</returns>
        //IFileUploadInfoExecResult GetUploadResumeInfo(byte[] fileMD5Hash);

        //IFileUploadInfoExecResult GetUploadResumeInfo(long fileID);

        ///// <summary>
        ///// Retrieves the Upload Resume information of a file.
        ///// </summary>
        ///// <param name="file">File Info.</param>
        ///// <returns>Will return File Management Execution result, see <see cref="IFileManagementExecResult"/> for more information.</returns>
        //IFileUploadInfoExecResult GetUploadResumeInfo(FileInfo file);

        ///// <summary>
        ///// Retrieves the Upload Resume information of a file.
        ///// </summary>
        ///// <param name="filePath">File Path.</param>
        ///// <returns>Will return File Management Execution result, see <see cref="IFileManagementExecResult"/> for more information.</returns>
        //IFileUploadInfoExecResult GetUploadResumeInfo(string filePath);


        /// <summary>
        /// Opens a windows upload dialog box.
        /// </summary>
        /// <param name="dialog">Boolean, modal or not.</param>
        void OpenUploadWindow(bool dialog);

        void OpenUploadWindow(bool dialog, MetaData metaData);

        #endregion

        #region Events

        /// <summary>
        /// Event for progress during file uploading.  See <see cref="FileUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<FileUploadProgressArgs> OnFileUploadProgress;

        /// <summary>
        /// Event for file progress during bulk/multiple files uploading.  See <see cref="TotalUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<TotalUploadProgressArgs> OnTotalUploadProgress;

        /// <summary>
        /// Event for total upload complete during bulk/multiple files uploading.  See <see cref="FileUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<FileUploadMessageArgs> OnTotalUploadComplete;

        /// <summary>
        /// Event for single file upload complete.  See <see cref="FileUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<FileUploadMessageArgs> OnUploadComplete;

        /// <summary>
        /// Event triggered if upload is stopped.  See <see cref="FileUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<FileUploadMessageArgs> OnUploadStopped;

        /// <summary>
        /// Event triggered if upload encounters error.  See <see cref="FileUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<FileUploadMessageArgs> OnUploadError;

        /// <summary>
        /// Event for notification during uploading process.  See <see cref="FileUploadProgressArgs"/> for the event argument properties.
        /// </summary>
        event EventHandler<FileUploadMessageArgs> OnNewMessage;

        #endregion

        #region Files
        /// <summary>
        /// Create a session instance of a StoredFile from a given fileId
        /// </summary>
        /// <param name="fileId">The StoredFile Id, to instanciate</param>
        /// <returns>Will return IStoredFile, see <see cref="IStoredFile"/> for more information.</returns>
        /// <example>
        /// <code>
        ///     //create new session
        ///     ISession session = new Session();
        ///     if (session.Login("username", "password").Status != Enums.ExecutionResults.Success)
        ///     {
        ///         Console.WriteLine(string.Format("Failed to login to Diomede service."));
        ///         return;
        ///     }
        /// 
        ///     IFileManagement fileMgr = session as IFileManagement;
        ///
        ///     int fileId = 15; //sample file id
        ///     //create session instance of the file
        ///     IStoredFile file = fileMgr.StoredFileInstance(fileId);
        /// 
        ///     //move the StoreFile to Archive
        ///     IStoredFileExecResult result = file.MoveToTier(Diomede.SDK.Enums.StorageTiers.ArchiveStorage);
        ///     if (result.Status == Enums.ExecutionResults.Success)
        ///         Console.WriteLine("File is successfully moved to archive.");
        ///     else
        ///         Console.WriteLine(string.Format("Failed to move file, error: {0}", result.Message));
        /// 
        /// </code>
        /// <code lang="VB.NET">
        /// 'create new session
        /// Dim session As ISession = New Session()
        /// If Not (session.Login("username", "password").Status = Enums.ExecutionResults.Success) Then
        ///     Console.WriteLine(String.Format("Failed to login to Diomede service."))
        ///     Return
        /// End If
        /// 'sample file id
        /// Dim fileId As Integer = 15
        /// Dim fileMgr As IFileManagement = session
        /// 'create session instance of the file
        /// Dim file As IStoredFile = fileMgr.StoredFileInstance(fileId)
        /// 'move file to archive
        /// Dim result As IStoredFileExecResult = file.MoveToTier(Enums.StorageTiers.ArchiveStorage)
        /// If (result.Status = Enums.ExecutionResults.Success) Then
        ///     Console.WriteLine("File is successfully moved to archive.")
        /// Else
        ///     Console.WriteLine(String.Format("Failed to move file, error: {0}", result.Message))
        /// End If
        /// 
        /// </code>
        /// </example>
        IStoredFile StoredFileInstance(long fileId);

        /// <summary>
        /// Create a session instance of a StoredFile from a given FileProperties, see <see cref="IFileManagement.StoredFileInstance(int)"/> for sample codes.
        /// </summary>
        /// <param name="file">The FileProperty to intanciate.</param>
        /// <returns>Will return IStoredFile, see <see cref="IStoredFile"/> for more information.</returns>
        IStoredFile StoredFileInstance(FileProperties file);
        #endregion

        #region MetaData
        IGetMetaDataExecResult GetMetaData(int? metaDataId, string name, string value);

        ICreateMetaDataExecResult CreateMetaData(string name, string value);
        #endregion

        #region Utils
        int ChunkSize { get;set;}

        /// <summary>
        /// No SDK Tester.
        /// </summary>
        void NoSDKTester();
        #endregion
    }

    #endregion

    #region ExecResults
    /// <summary>
    /// Provide interface for FileManagement bulk uploading result.
    /// </summary>
    public interface IFileManagementBulkUploadExecResult
    {
        /// <summary>
        /// Result status for the execution of a session methods,
        /// see <see cref="Enums.ExecutionResults"/> for more information.
        /// </summary>
        ExecutionResults Status { get; set; }

        /// <summary>
        /// Result message for the execution of a File management methods
        /// </summary>
        string Message { get; set; }

        /// <summary>
        /// Holds information for the upload result, see <see cref="IFileManagementExecResult"/> for more information.
        /// </summary>
        List<IFileManagementExecResult> UploadResults { get; set; }
    }

    /// <summary>
    /// Provide interface for FileManagement execution result
    /// </summary>
    public interface IFileManagementExecResult
    {
        /// <summary>
        /// Result status for the execution of a session methods,
        /// see <see cref="Enums.ExecutionResults"/> for more information.
        /// </summary>
        ExecutionResults Status { get; set; }

        /// <summary>
        /// Result message for the execution of a File management methods
        /// </summary>
        string Message { get; set; }

        /// <summary>
        /// Hold stored files information, if the methods return stored files.
        /// </summary>
        List<IStoredFile> StoredFiles { get; set; }

        long TotalResultCount { get;set;}
    }

    public interface ISearchFilesSummaryResult : IExecResult
    {
        SearchFilesTotalInfo FileTotalInfo { get; set;}
    }

    /// <summary>
    /// Provide interface for File Upload  execution result 
    /// </summary>
    public interface IFileUploadInfoExecResult : IExecResult
    {
        /// <summary>
        /// Boolean. Return TRUE/FALSE whether or not the upload is complete.
        /// </summary>
        bool IsComplete { get; set;}

        /// <summary>
        /// The offset of the result.
        /// </summary>
        long Offset { get;set;}
    }

    public interface IGetUploadTokenExecResult : IExecResult
    {
        string UploadToken { get; set;}
    }

    public interface IGetMetaDataExecResult : IExecResult
    {
        List<MetaData> MetaData { get;set;}
    }

    public interface ICreateMetaDataExecResult : IExecResult
    {
        int MetaDataID { get; set; }
    }

    public interface ICreateFileExecResult : IExecResult
    {
        long FileID { get;set;}
    }

    public interface IUploadExecResult : IExecResult
    {
        long FileID { get;set;}
    }

    #endregion

    #region Exec results implementations
    public class CreateMetaDataExecResult : ICreateMetaDataExecResult
    {

        public CreateMetaDataExecResult()
        { }

        public CreateMetaDataExecResult(Exception ex)
        {
            status = ExecutionResults.Failed;
            message = ex.Message;
        }

        public CreateMetaDataExecResult(int mdId)
        {
            status = ExecutionResults.Success;
            message = "Execution Successful.";
            metaDataID = mdId;
        }

        #region ICreateMetaDataExecResult Members

        int metaDataID;
        int ICreateMetaDataExecResult.MetaDataID
        {
            get
            {
                return metaDataID;
            }
            set
            {
                metaDataID = value;
            }
        }

        #endregion

        #region IExecResult Members

        ExecutionResults status;
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }

        string message;
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion
    }

    /// <summary>
    /// Interface for Search File Summary Result.
    /// </summary>
    public class SearchFilesSummaryResult : ISearchFilesSummaryResult
    {
        /// <summary>
        /// Creates instance of SearchFilesSummaryResult that will accept status and message.
        /// </summary>
        /// <param name="status">Execution Results Status.</param>
        /// <param name="message">Result message.</param>
        public SearchFilesSummaryResult(ExecutionResults status, string message)
        {
            ISearchFilesSummaryResult t = this;
            t.Status = status;
            t.Message = message;
        }

        /// <summary>
        /// Object constructor that will accept status, message, and StoreFile.
        /// </summary>
        /// <param name="status">Execution Result Status.</param>
        /// <param name="message">Result message.</param>
        /// <param name="totalFiles">Total number of files.</param>
        /// <param name="totalBytes">Total number of bytes.</param>
        /// <param name="watts">Watts.</param>
        public SearchFilesSummaryResult(ExecutionResults status, string message, SearchFilesTotalInfo info)
        {
            ISearchFilesSummaryResult t = this;
            t.Status = status;
            t.Message = message;
            t.FileTotalInfo = info;
        }

        /// <summary>
        /// Object constructor that will accept Exception, will set the Status = Failed, and Message = Exception.Message
        /// </summary>
        /// <param name="ex">Exception</param>
        public SearchFilesSummaryResult(Exception ex)
        {
            ISearchFilesSummaryResult t = this;
            t.Status = ExecutionResults.Failed;
            t.Message = ex.Message;
        }

        #region ISearchFilesSummaryResult Members


        SearchFilesTotalInfo fileTotalInfo;
        SearchFilesTotalInfo ISearchFilesSummaryResult.FileTotalInfo
        {
            get
            {
                return fileTotalInfo;
            }
            set
            {
                fileTotalInfo = value;
            }
        }
        #endregion

        #region IExecResult Members
        ExecutionResults status;
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }

        string message;
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion
    }

    public class GetMetaDataExecResult : IGetMetaDataExecResult
    {
        public GetMetaDataExecResult()
        {
        }

        public GetMetaDataExecResult(MetaData[] metaData)
        {
            status = ExecutionResults.Success;
            message = "GetMetaData successfully executed.";
            this.metaData = new List<MetaData>(metaData);
        }

        public GetMetaDataExecResult(Exception ex)
        {
            status = ExecutionResults.Failed;
            message = ex.Message;
        }

        #region IGetMetaDataExecResult Members

        List<MetaData> metaData;
        List<MetaData> IGetMetaDataExecResult.MetaData
        {
            get
            {
                return metaData;
            }
            set
            {
                metaData = value;
            }
        }

        #endregion

        #region IExecResult Members

        ExecutionResults status;
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }

        string message;
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion
    }

    public class GetUploadTokenExecResult : IGetUploadTokenExecResult
    {
        public GetUploadTokenExecResult()
        {
        }

        public GetUploadTokenExecResult(Exception ex)
        {
            this.status = ExecutionResults.Failed;
            this.message = ex.Message;
            this.uploadToken = string.Empty;
        }

        public GetUploadTokenExecResult(string uploadToken)
        {
            this.status = ExecutionResults.Success;
            this.message = "Execution successful.";
            this.uploadToken = uploadToken;
        }

        #region IGetUploadTokenExecResult Members

        string uploadToken;
        string IGetUploadTokenExecResult.UploadToken
        {
            get
            {
                return uploadToken;
            }
            set
            {
                uploadToken = value;
            }
        }

        #endregion

        #region IExecResult Members

        ExecutionResults status;
        /// <summary>
        /// IExecResult.Status implementation, see <see cref="IExecResult.Status"/> for more information.
        /// </summary>
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }
        string message;
        /// <summary>
        /// IIExecResult.Message implementation, see <see cref="IExecResult.Message"/> for more information.
        /// </summary>
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion
    }

    /// <summary>
    /// IFileUploadInfoExecResult implementation, see <see cref="IFileUploadInfoExecResult"/> for more information.
    /// </summary>
    public class FileUploadInfoExecResult : IFileUploadInfoExecResult
    {
        /// <summary>
        /// Object constructor that will accept status and message parameters.
        /// </summary>
        /// <param name="status">Result status</param>
        /// <param name="message">Result message</param>
        public FileUploadInfoExecResult(ExecutionResults status, string message)
        {
            IFileUploadInfoExecResult t = this;
            t.Status = status;
            t.Message = message;
        }

        /// <summary>
        /// Object constructor that will accept status, message, offset and isComplete.
        /// </summary>
        /// <param name="status">Result status.</param>
        /// <param name="message">Result message.</param>
        /// <param name="offset">Offset.</param>
        /// <param name="isComplete">Is Complete.</param>
        public FileUploadInfoExecResult(ExecutionResults status, string message, long offset, bool isComplete)
        {
            IFileUploadInfoExecResult t = this;
            t.Status = status;
            t.Message = message;
            t.IsComplete = isComplete;
            t.Offset = offset;
        }

        /// <summary>
        /// Object constructor that will accept Exception, will set the Status = Failed, and Message = Exception.Message
        /// </summary>
        /// <param name="ex">Exception</param>
        public FileUploadInfoExecResult(Exception ex)
        {
            IFileUploadInfoExecResult t = this;
            t.Status = ExecutionResults.Failed;
            t.Message = ex.Message;
        }

        #region IFileUploadInfoExecResult Members
        bool isComplete;
        /// <summary>
        /// IFileUploadInfoExecResult.IsComplete, see <see cref="IFileUploadInfoExecResult.IsComplete"/> for more information.
        /// </summary>
        bool IFileUploadInfoExecResult.IsComplete
        {
            get
            {
                return isComplete;
            }
            set
            {
                isComplete = value;
            }
        }

        long offset;
        /// <summary>
        /// IFileUploadInfoExecResult.Offset, see <see cref="IFileUploadInfoExecResult.Offset"/> for more information.
        /// </summary>
        long IFileUploadInfoExecResult.Offset
        {
            get
            {
                return offset;
            }
            set
            {
                offset = value;
            }
        }

        #endregion

        #region IExecResult Members

        ExecutionResults status;
        /// <summary>
        /// IExecResult.Status implementation, see <see cref="IExecResult.Status"/> for more information.
        /// </summary>
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }
        string message;
        /// <summary>
        /// IIExecResult.Message implementation, see <see cref="IExecResult.Message"/> for more information.
        /// </summary>
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion
    }

    /// <summary>
    /// IFileManagementExecResult implementation, see <see cref="IFileManagementExecResult"/> for more information.
    /// </summary>
    public class FileManagementExecResult : IFileManagementExecResult
    {
        /// <summary>
        /// Default constructor.
        /// </summary>
        public FileManagementExecResult()
        {
        }

        /// <summary>
        /// Object constructor that will accept status and message parameters.
        /// </summary>
        /// <param name="status">Result status</param>
        /// <param name="message">Result message</param>
        public FileManagementExecResult(ExecutionResults status, string message)
        {
            IFileManagementExecResult t = this;
            t.Status = status;
            t.Message = message;
            t.StoredFiles = new List<IStoredFile>();
        }

        /// <summary>
        /// Object constructor that will accept status, message, and StoreFile.
        /// </summary>
        /// <param name="status">Result status.</param>
        /// <param name="message">Result message.</param>
        /// <param name="storedFile">Result StoreFile.</param>
        public FileManagementExecResult(ExecutionResults status, string message, IStoredFile storedFile)
        {
            IFileManagementExecResult t = this;
            t.Status = status;
            t.Message = message;
            t.StoredFiles = new List<IStoredFile>();
            t.StoredFiles.Add(storedFile);
        }

        /// <summary>
        /// Object constructor that will accept Exception, will set the Status = Failed, and Message = Exception.Message
        /// </summary>
        /// <param name="ex">Exception</param>
        public FileManagementExecResult(Exception ex)
        {
            IFileManagementExecResult t = this;
            t.Status = ExecutionResults.Failed;
            t.Message = ex.Message;
        }

        #region IFileManagementExecResult Members

        private ExecutionResults status;

        /// <summary>
        /// IFileManagementExecResult.Status implementation, see <see cref="IFileManagementExecResult.Status"/> for more information.
        /// </summary>
        ExecutionResults IFileManagementExecResult.Status
        {
            get { return status; }
            set { status = value; }
        }

        private string message;
        /// <summary>
        /// IFileManagementExecResult.Message implementation, see <see cref="IFileManagementExecResult.Message"/> for more information.
        /// </summary>
        string IFileManagementExecResult.Message
        {
            get { return message; }
            set { message = value; }
        }

        private List<IStoredFile> storedFiles;
        /// <summary>
        /// IFileManagementExecResult.StoreFiles implementation, see <see cref="IFileManagementExecResult.StoredFiles"/> for more information.
        /// </summary>
        List<IStoredFile> IFileManagementExecResult.StoredFiles
        {
            get { return storedFiles; }
            set { storedFiles = value; }
        }

        long totalResultCount;
        long IFileManagementExecResult.TotalResultCount
        {
            get
            {
                return totalResultCount;
            }
            set
            {
                totalResultCount = value;
            }
        }
        #endregion


    }

    /// <summary>
    /// Implementation of FileManagement bulk uploading result, see <see cref="IFileManagementBulkUploadExecResult"/>
    /// </summary>
    public class FileManagementBulkUploadExecResult : IFileManagementBulkUploadExecResult
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        public FileManagementBulkUploadExecResult()
        {
            uploadResults = new List<IFileManagementExecResult>();
        }

        /// <summary>
        /// Object constuctor that will accept status and message as parameters.
        /// </summary>
        /// <param name="status">Result status</param>
        /// <param name="message">Result message</param>
        public FileManagementBulkUploadExecResult(ExecutionResults status, string message)
        {
            this.status = status;
            this.message = message;
            uploadResults = new List<IFileManagementExecResult>();
        }

        #region IFileManagementBulkUploadExecResult Members

        private ExecutionResults status;

        /// <summary>
        /// IFileManagementBulkUploadExecResult.Status implementation, see <see cref="IFileManagementBulkUploadExecResult.Status"/> for more information.
        /// </summary>
        ExecutionResults IFileManagementBulkUploadExecResult.Status
        {
            get { return status; }
            set { status = value; }
        }

        private string message;

        /// <summary>
        /// IFileManagementBulkUploadExecResult.Message implementation, see <see cref="IFileManagementBulkUploadExecResult.Message"/> for more information.
        /// </summary>
        string IFileManagementBulkUploadExecResult.Message
        {
            get { return message; }
            set { message = value; }
        }

        private List<IFileManagementExecResult> uploadResults;

        /// <summary>
        /// IFileManagementBulkUploadExecResult.UploadResults implementation, see <see cref="IFileManagementBulkUploadExecResult.UploadResults"/> for more information.
        /// </summary>
        List<IFileManagementExecResult> IFileManagementBulkUploadExecResult.UploadResults
        {
            get { return uploadResults; }
            set { uploadResults = value; }
        }

        #endregion
    }

    public class CreateFileExecResult : ICreateFileExecResult
    {

        public CreateFileExecResult()
        { 
        }

        public CreateFileExecResult(long fileID)
        {
            status = ExecutionResults.Success;
            this.fileID = fileID;
            message = "Create file execution successful.";
        }

        public CreateFileExecResult(Exception ex)
        {
            status = ExecutionResults.Failed;
            message = ex.Message;
        }

        #region ICreateFileExecResult Members

        long fileID;
        long ICreateFileExecResult.FileID
        {
            get
            {
                return fileID;
            }
            set
            {
                fileID = value;
            }
        }

        #endregion

        #region IExecResult Members

        ExecutionResults status;
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }

        string message;
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion
    }

    public class UploadExecResult : IUploadExecResult
    {
        public UploadExecResult()
        {
            status = ExecutionResults.Success;
            message = "Upload execution successful.";
        }

        public UploadExecResult(Exception ex)
        {
            status = ExecutionResults.Failed;
            message = ex.Message;
        }

        public UploadExecResult(long fileID)
        {
            status = ExecutionResults.Success;
            message = "Execution Successful.";
            this.fileID = fileID;
        }


        #region IExecResult Members

        ExecutionResults status;
        ExecutionResults IExecResult.Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
            }
        }

        string message;
        string IExecResult.Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion

        #region IUploadExecResult Members

        long fileID;
        long IUploadExecResult.FileID
        {
            get
            {
                return fileID;
            }
            set
            {
                fileID = value;
            }
        }

        #endregion
    }

    #endregion

    #region Event Args
    /// <summary>
    /// Event argument object used to send message on upload process
    /// </summary>
    public class FileUploadMessageArgs : EventArgs
    {
        /// <summary>
        /// Creates new instance of FileUploadMessageArgs.
        /// </summary>
        public FileUploadMessageArgs()
        { }

        /// <summary>
        /// Creates new instance of FileUploadMessageArgs with a string message as parameter.
        /// </summary>
        /// <param name="message">Message.</param>
        public FileUploadMessageArgs(string message)
        {
            Message = message;
        }

        /// <summary>
        /// The event message.
        /// </summary>
        public string Message;
    }

    /// <summary>
    /// Event argument object use by <see cref="IFileManagement.OnFileUploadProgress">IFileManagement.OnFileUploadProgress</see>.
    /// </summary>
    public class FileUploadProgressArgs : EventArgs
    {
        /// <summary>
        /// Number of bytes currently read.
        /// </summary>
        public long BytesRead;

        /// <summary>
        /// Total number of bytes of the file to upload.
        /// </summary>
        public long Length;

        /// <summary>
        /// Class constructor that will accpet bytes read, and length
        /// </summary>
        /// <param name="BytesRead">Number of bytes read</param>
        /// <param name="Length">File's total number of bytes</param>
        public FileUploadProgressArgs(long BytesRead, long Length)
        {
            this.BytesRead = BytesRead;
            this.Length = Length;
        }

        /// <summary>
        /// A ready to use method for displaying progress percentage string."
        /// </summary>
        /// <returns>Sample return "45 %"</returns>
        public string ToPercentString()
        {
            return string.Format("{0} %", ((double)BytesRead / (double)Length * 100));
        }

        /// <summary>
        /// A ready to use method for displayin progress string.
        /// </summary>
        /// <returns>Sample return format "345 of 1206"</returns>
        public string ToProgressString()
        {
            return string.Format("{0} of {1}", BytesRead, Length);
        }
    }

    /// <summary>
    /// Event argument used by <see cref="IFileManagement.OnTotalUploadProgress">IFileManagement.OnTotalUploadProgress</see>.
    /// </summary>
    public class TotalUploadProgressArgs : EventArgs
    {
        private long count;

        /// <summary>
        /// Total number of files to be uploaded
        /// </summary>
        public long Count
        {
            get { return count; }
            set { count = value; }
        }

        private long uploaded;

        /// <summary>
        /// Number of files that are already uploaded.
        /// </summary>
        public long Uploaded
        {
            get { return uploaded; }
            set { uploaded = value; }
        }

        /// <summary>
        /// Default constructor
        /// </summary>
        public TotalUploadProgressArgs()
        {
        }

        /// <summary>
        /// Object constructor that will accept files uploaded and count.
        /// </summary>
        /// <param name="uploaded">Files already uploaded</param>
        /// <param name="count">Number of files to upload</param>
        public TotalUploadProgressArgs(long uploaded, long count)
        {
            this.uploaded = uploaded;
            this.count = count;
        }

        /// <summary>
        /// A ready to use method for displaying progress percentage string."
        /// </summary>
        /// <returns>Sample return "45 %"</returns>
        public string ToPercentString()
        {
            return string.Format("{0} %", ((double)uploaded / (double)count * 100));
        }

        /// <summary>
        /// A ready to use method for displayin progress string.
        /// </summary>
        /// <returns>Sample return format "3 of 34"</returns>
        public string ToProgressString()
        {
            return string.Format("Uploading {0} of {1}..", uploaded, count);
        }
    }

    #endregion

    #region Main Implementation
    /// <summary>
    /// IFileManagement implementation, for more information see <see cref="IFileManagement"/>
    /// </summary>
    public partial class Session : IFileManagement
    {
        #region Searching

        /// <summary>
        /// IFileManagement.SearchFiles implementation, see <see cref="IFileManagement.SearchFiles(SearchFilter)"/> for more information.
        /// </summary>
        /// <param name="filter">Filter parameter in searching files.</param>
        /// <returns>Will return Status = Success, and list of stored files if file is successfully executed.</returns>
        IFileManagementExecResult IFileManagement.SearchFiles(System.Nullable<long> fileID, string fileName, string hashMD5, string hashSHA1, System.Nullable<long> minSize, System.Nullable<long> maxSize, System.Nullable<System.DateTime> dateStart, System.Nullable<System.DateTime> dateEnd, System.Nullable<bool> isDeleted, System.Nullable<bool> isComplete, string metaName, string metaValue, long offset, long pageSize)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new FileManagementExecResult(ExecutionResults.Failed, "No active session.");

            try
            {
                long totalResults;
                FileProperties[] files = service.SearchFiles(token, fileID, fileName, hashMD5, hashSHA1, minSize, maxSize, dateStart, dateEnd, isDeleted, isComplete, metaName, metaValue, offset, pageSize, out totalResults);
                IFileManagementExecResult result = new FileManagementExecResult(ExecutionResults.Success, "");
                result.TotalResultCount = totalResults;

                foreach (FileProperties file in files)
                {
                    result.StoredFiles.Add((this as IFileManagement).StoredFileInstance(file));
                }
                return result;
            }
            catch (Exception ex)
            {
                return new FileManagementExecResult(ex);
            }
        }

        ISearchFilesSummaryResult IFileManagement.SearchFilesSummary(long? fileID, string fileName, string hashMD5, string hashSHA1, long? minSize, long? maxSize, DateTime? dateStart, DateTime? dateEnd, bool? isDeleted, bool? displayIncompleteFiles, string metaName, string metaValue)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new SearchFilesSummaryResult(ExecutionResults.Failed, "No active session.");

            try
            {
                
                SearchFilesTotalInfo s = service.SearchFilesTotal(token, fileID, fileName, hashMD5, hashSHA1, minSize, maxSize, dateStart, dateEnd, displayIncompleteFiles, metaName, metaValue);

                return new SearchFilesSummaryResult(ExecutionResults.Success, "Search file summary sucessful.", s);
            }
            catch (Exception ex)
            {
                return new SearchFilesSummaryResult(ex);
            }
        }

        //IFileManagementExecResult IFileManagement.Upload(FileInfo file)
        //{
        //    return (this as IFileManagement).Upload(file, string.Empty, string.Empty);
        //}

        private int chunkSize = 1048576;

        //public int ChunkSize
        //{
        //    get { return chunkSize; }
        //    set { chunkSize = value; }
        //}


        void onNewMessageHandler(string message)
        {
            if (onNewMessage != null)
            {
                onNewMessage(this, new FileUploadMessageArgs(message));
            }
        }

        void onUploadCompleteHandler(string message)
        {
            if (onUploadComplete != null)
            {
                onUploadComplete(this, new FileUploadMessageArgs(message));
            }
        }

        void onFileUploadProgressHandler(long read, long length)
        {
            if (onFileUploadProgress != null)
            {
                onFileUploadProgress(this, new FileUploadProgressArgs(read, length));
            }
        }

        //IFileManagementExecResult IFileManagement.Upload(FileInfo file, string contentEncoding, string callbackAddress)
        //{
        //    if (service == null || string.IsNullOrEmpty((this as ISession).Token))
        //        return new FileManagementExecResult(ExecutionResults.Failed, "No active session.");

        //    if (transfer == null)
        //        transfer = new DiomedeStorageTransferClient();

        //    try
        //    {
        //        if (chunkSize == 0)
        //            chunkSize = 1048576;

        //        int uploadChunk = chunkSize;

        //        using (FileStream stream = file.OpenRead())
        //        {
        //            if (uploadChunk > file.Length)
        //            {
        //                uploadChunk = System.Convert.ToInt32(file.Length);
        //            }

        //            //upload the file by chunks
        //            int readLen;
        //            long uploadedLen = 0;
        //            byte[] buffer = new byte[uploadChunk];

        //            onNewMessageHandler("Preparing file's hash id.");


        //            //get the File's MD5 hash
        //            string md5Hash = Utilities.GetFileMD5Hash(file.FullName);
        //            long? fileid = null;

        //            //check if file is already uploaded
        //            onNewMessageHandler("Checking resume information.");

        //            IFileUploadInfoExecResult uinfo = (this as IFileManagement).GetUploadResumeInfo(Convert.FromBase64String(md5Hash));
        //            //check if file is already completely uploaded
        //            if (uinfo.IsComplete)
        //            {
        //                onUploadCompleteHandler("Upload is already complete.");
        //                return new FileManagementExecResult(ExecutionResults.Success, "Upload is already complete.");
        //            }
        //            else
        //            {
        //                //if offset is greater than 0 then there is already initial uploaded file, 
        //                //we will upload starting from the returned offset
        //                if (uinfo.Offset > 0)
        //                {
        //                    onNewMessageHandler("Resuming upload.");
        //                    stream.Seek(uinfo.Offset, SeekOrigin.Begin);
        //                    uploadedLen = uinfo.Offset;
        //                }
        //            }
        //            try
        //            {
        //                //start uploading
        //                while (true)
        //                {
        //                    //read a chunk from file
        //                    readLen = stream.Read(buffer, 0, uploadChunk);
        //                    if (readLen == 0)
        //                        break;
        //                    //resize the buffer if required
        //                    if (readLen < buffer.Length)
        //                        Array.Resize<byte>(ref buffer, readLen);
        //                    //convert the buffer into memory stream
        //                    MemoryStream memstream = new MemoryStream(buffer);

        //                    uploadedLen += readLen;
        //                    onFileUploadProgressHandler(uploadedLen, stream.Length);
        //                    // upload the chunk
        //                    fileid = transfer.Upload(true, callbackAddress, contentEncoding, memstream.Length, file.Name, md5Hash, token, stream.Length, memstream);
        //                    //check if upload is complete
        //                    if (uploadedLen == stream.Length)
        //                        break;
        //                }
        //                //raise upload completed
        //                onUploadCompleteHandler("Upload complete.");
        //                return new FileManagementExecResult(ExecutionResults.Success, "Upload successful.",
        //                                                (this as IFileManagement).StoredFileInstance((int)fileid.Value));

        //            }
        //            catch (Exception ex)
        //            {
        //                return new FileManagementExecResult(ex);
        //            }


        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        return new FileManagementExecResult(ex);
        //    }
        //}

        //IFileManagementExecResult IFileManagement.Upload(FileInfo file, string contentEncoding, string callbackAddress, long? FileID)
        //{
        //    if (service == null || string.IsNullOrEmpty((this as ISession).Token))
        //        return new FileManagementExecResult(ExecutionResults.Failed, "No active session.");

        //    if (transfer == null)
        //        transfer = new DiomedeStorageTransferClient();

        //    try
        //    {
        //        if (chunkSize == 0)
        //            chunkSize = 1048576;

        //        int uploadChunk = chunkSize;

        //        using (FileStream stream = file.OpenRead())
        //        {
        //            if (uploadChunk > file.Length)
        //            {
        //                uploadChunk = System.Convert.ToInt32(file.Length);
        //            }

        //            //upload the file by chunks
        //            int readLen;
        //            long uploadedLen = 0;
        //            byte[] buffer = new byte[uploadChunk];

        //            onNewMessageHandler("Preparing file's hash id.");

        //            //get the File's MD5 hash
        //            //string md5Hash = Utilities.GetFileMD5Hash(file.FullName);
        //            long? fileid = FileID;

        //            //check if file is already uploaded
        //            onNewMessageHandler("Checking resume information.");

        //            if (fileid.HasValue)
        //            {
        //                IFileUploadInfoExecResult uinfo = (this as IFileManagement).GetUploadResumeInfo(fileid.Value);
        //                //check if file is already completely uploaded
        //                if (uinfo.IsComplete)
        //                {
        //                    onUploadCompleteHandler("Upload is already complete.");
        //                    return new FileManagementExecResult(ExecutionResults.Success, "Upload is already complete.");
        //                }
        //                else
        //                {
        //                    //if offset is greater than 0 then there is already initial uploaded file, 
        //                    //we will upload starting from the returned offset
        //                    if (uinfo.Offset > 0)
        //                    {
        //                        onNewMessageHandler("Resuming upload.");
        //                        stream.Seek(uinfo.Offset, SeekOrigin.Begin);
        //                        uploadedLen = uinfo.Offset;
        //                    }
        //                }
        //            }
        //            try
        //            {
        //                //start uploading
        //                while (true)
        //                {
        //                    //read a chunk from file
        //                    readLen = stream.Read(buffer, 0, uploadChunk);
        //                    if (readLen == 0)
        //                        break;
        //                    //resize the buffer if required
        //                    if (readLen < buffer.Length)
        //                        Array.Resize<byte>(ref buffer, readLen);
        //                    //convert the buffer into memory stream
        //                    MemoryStream memstream = new MemoryStream(buffer);

        //                    uploadedLen += readLen;
        //                    onFileUploadProgressHandler(uploadedLen, stream.Length);
        //                    // upload the chunk
        //                    fileid = transfer.UploadWithFileID(true, callbackAddress, contentEncoding, memstream.Length, fileid, file.Name, token, stream.Length, memstream);
        //                    //check if upload is complete
        //                    if (uploadedLen == stream.Length)
        //                        break;
        //                }
        //                //raise upload completed
        //                onUploadCompleteHandler("Upload complete.");
        //                return new FileManagementExecResult(ExecutionResults.Success, "Upload successful.",
        //                                                (this as IFileManagement).StoredFileInstance((int)fileid.Value));

        //            }
        //            catch (Exception ex)
        //            {
        //                return new FileManagementExecResult(ex);
        //            }


        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        return new FileManagementExecResult(ex);
        //    }
        //}

        private void fileupload_ProgressChanged(object sender, FileUploadProgressArgs e)
        {
            if (onFileUploadProgress != null)
                onFileUploadProgress(this, e);
        }
        /// <summary>
        /// IFileManagement.Upload implementation, see <see cref="IFileManagement.Upload(string, StorageInfo)"/> for more information.
        /// </summary>
        /// <param name="filename">File path of file to be uploaded.</param>
        /// <param name="storageType">Storage storageType where the file to be uploaded.</param>
        /// <returns>Will return Status = Success if file is successfully uploaded.</returns>
        //IFileManagementExecResult IFileManagement.Upload(string filename, StorageInfo storageType)
        //{
        //    FileInfo file = new FileInfo(filename);
        //    return (this as IFileManagement).Upload(file);
        //}
        ///// <summary>
        ///// IFileManagement.Upload implementation, see <see cref="IFileManagement.Upload(FileInfo[], StorageInfo)"/> for more information.
        ///// </summary>
        ///// <param name="files">Array of FileInfo's to be uploaded.</param>
        ///// <param name="storageType">Storage storageType where the file to be uploaded.</param>
        ///// <returns>Will return Status = Success if file is successfully uploaded.</returns>
        //IFileManagementBulkUploadExecResult IFileManagement.Upload(FileInfo[] files, StorageInfo storageType)
        //{
        //    IFileManagementBulkUploadExecResult result =
        //        new FileManagementBulkUploadExecResult(ExecutionResults.Success, "");
        //    int index = 0;
        //    foreach (FileInfo f in files)
        //    {
        //        index++;
        //        if (onTotalUploadProgress != null)
        //            onTotalUploadProgress(this, new TotalUploadProgressArgs(index, files.Length));
        //        IFileManagementExecResult upresult = (this as IFileManagement).Upload(f);
        //        result.UploadResults.Add(upresult);
        //        if (upresult.Status != ExecutionResults.Success)
        //        {
        //            result.Status = ExecutionResults.Incomplete;
        //            result.Message = "Upload incomplete.";
        //        }
        //    }
        //    return result;
        //}

        ///// <summary>
        ///// IFileManagement.Upload implementation, see <see cref="IFileManagement.Upload(string[], StorageInfo)"/> for more information.
        ///// </summary>
        ///// <param name="filenames">Array of file path's to be uploaded.</param>
        ///// <param name="storageType">Storage storageType where the file to be uploaded.</param>
        ///// <returns>Will return Status = Success if file is successfully uploaded.</returns>
        //IFileManagementBulkUploadExecResult IFileManagement.Upload(string[] filenames, StorageInfo storageType)
        //{
        //    IFileManagementBulkUploadExecResult result =
        //        new FileManagementBulkUploadExecResult(ExecutionResults.Success, "");

        //    int index = 0;
        //    foreach (string f in filenames)
        //    {
        //        index++;
        //        if (onTotalUploadProgress != null)
        //            onTotalUploadProgress(this, new TotalUploadProgressArgs(index, filenames.Length));

        //        IFileManagementExecResult upresult = (this as IFileManagement).Upload(f, storageType);
        //        result.UploadResults.Add(upresult);
        //        if (upresult.Status != ExecutionResults.Success)
        //        {
        //            result.Status = ExecutionResults.Incomplete;
        //            result.Message = "Upload incomplete.";
        //        }
        //    }
        //    if (onTotalUploadComplete != null)
        //        onTotalUploadComplete(this, new FileUploadMessageArgs("Folder Upload Complete."));
        //    return result;
        //}

        IGetUploadTokenExecResult IFileManagement.GetUploadToken(string fileName, string callback)
        {
            if (service == null || string.IsNullOrEmpty(token))
                return new GetUploadTokenExecResult(new Exception("No active user."));
            try
            {
                FileInfo fi = new FileInfo(fileName);

                string uploadToken = service.GetUploadToken(token, fileName, fi.Length, callback);
                return new GetUploadTokenExecResult(uploadToken);
            }
            catch (Exception ex)
            {
                return new GetUploadTokenExecResult(ex);
            }
        }

        private EventHandler<FileUploadProgressArgs> onFileUploadProgress;
        /// <summary>
        /// See <see cref="IFileManagement.OnFileUploadProgress"/> for more information.
        /// </summary>
        event EventHandler<FileUploadProgressArgs> IFileManagement.OnFileUploadProgress
        {
            add { onFileUploadProgress += value; }
            remove { onFileUploadProgress -= value; }
        }

        private EventHandler<TotalUploadProgressArgs> onTotalUploadProgress;
        /// <summary>
        /// See <see cref="IFileManagement.OnTotalUploadProgress"/> for more information.
        /// </summary>
        event EventHandler<TotalUploadProgressArgs> IFileManagement.OnTotalUploadProgress
        {
            add { onTotalUploadProgress += value; }
            remove { onTotalUploadProgress -= value; }
        }


        /// <summary>
        /// IFileManagement.StoredFileInstance implementation, see <see cref="IFileManagement.StoredFileInstance(int)"/> for more information.
        /// </summary>
        /// <param name="fileId">File id of stored file to be instanciated.</param>
        /// <returns>Session instance of the stored file, null if file id is invalid.</returns>
        IStoredFile IFileManagement.StoredFileInstance(long fileId)
        {
            IStoredFile sf = new StoredFile(fileId);
            sf.Session = this;
            return sf;
        }
        /// <summary>
        /// IFileManagement.StoredFileInstance implementation, see <see cref="IFileManagement.StoredFileInstance(FileProperties)"/> for more information.
        /// </summary>
        /// <param name="file">File property of file to be instanciated.</param>
        /// <returns>Session instance of the stored file, null if file id is invalid.</returns>
        IStoredFile IFileManagement.StoredFileInstance(FileProperties file)
        {
            IStoredFile sf = new StoredFile(file);
            sf.Session = this;
            return sf;
        }


        void IFileManagement.OpenUploadWindow(bool dialog)
        {
            //UI.FormUpload frm = new Diomede.SDK.UI.FormUpload();
            //frm.Session = this;
            //if (dialog)
            //    frm.ShowDialog();
            //else
            //    frm.Show();
            (this as IFileManagement).OpenUploadWindow(dialog, null);
        }

        void IFileManagement.OpenUploadWindow(bool dialog, MetaData metaData)
        {
            UI.FormUpload frm = new Diomede.SDK.UI.FormUpload(metaData);
            frm.Session = this;
            if (dialog)
                frm.ShowDialog();
            else
                frm.Show();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileID"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="ip"></param>
        /// <param name="offset"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        ISearchUploadLogsExecResult IFileManagement.SearchUploadLogs(long? fileID, DateTime? startDate, DateTime? endDate, string ip, long offset, long pageSize)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new SearchUploadLogsExecResult(ExecutionResults.Failed, "No active session.");

            try
            {
                long totalCount;
                UploadLogEntry[] logs = service.SearchUploadLog(token, (int)fileID.Value, startDate, endDate, ip, offset, pageSize, out totalCount);
                return new SearchUploadLogsExecResult(ExecutionResults.Success, "Search complete.", logs, totalCount);
            }
            catch (Exception ex)
            {
                return new SearchUploadLogsExecResult(ex);
            }

        }

        void IFileManagement.NoSDKTester()
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                throw new Exception("No active session.");

            IFileManagement f = this as IFileManagement;
            ISearchUploadLogsExecResult result = f.SearchUploadLogs(null, null, null, null, 0, 10);
            //long fileid = result.Logs[0].fileID;
            //service.RenameFile(token, (int)fileid, "Test");
            //service.DeleteFile(token, (int)fileid);
            //service.UndeleteFile(token, (int)fileid);
        }

        #endregion


        #region MetaData

        //IFileUploadInfoExecResult IFileManagement.GetUploadResumeInfo(long fileID)
        //{
        //    if (service == null || string.IsNullOrEmpty((this as ISession).Token))
        //        return new FileUploadInfoExecResult(ExecutionResults.Failed, "No active session.");

        //    if (transfer == null)
        //        transfer = new DiomedeStorageTransferClient();

        //    try
        //    {
        //        bool isComplete;
        //        long offset = transfer.GetUploadResumeInfoByFileID(token, fileID, out isComplete);
        //        return new FileUploadInfoExecResult(ExecutionResults.Success, "Execution complete.", offset, isComplete);
        //    }
        //    catch (Exception ex)
        //    {
        //        return new FileUploadInfoExecResult(ex);
        //    }
        //}

        //IFileUploadInfoExecResult IFileManagement.GetUploadResumeInfo(byte[] fileMD5Hash)
        //{
        //    if (service == null || string.IsNullOrEmpty((this as ISession).Token))
        //        return new FileUploadInfoExecResult(ExecutionResults.Failed, "No active session.");

        //    if (transfer == null)
        //        transfer = new DiomedeStorageTransferClient();

        //    try
        //    {
        //        bool isComplete;
        //        long offset = transfer.GetUploadResumeInfo(token, Convert.ToBase64String(fileMD5Hash), out isComplete);
        //        return new FileUploadInfoExecResult(ExecutionResults.Success, "Execution complete.", offset, isComplete);
        //    }
        //    catch (Exception ex)
        //    {
        //        return new FileUploadInfoExecResult(ex);
        //    }
        //}

        //IFileUploadInfoExecResult IFileManagement.GetUploadResumeInfo(FileInfo file)
        //{
        //    throw new Exception("The method or operation is not implemented.");
        //}

        //IFileUploadInfoExecResult IFileManagement.GetUploadResumeInfo(string filePath)
        //{
        //    throw new Exception("The method or operation is not implemented.");
        //}

        IGetMetaDataExecResult IFileManagement.GetMetaData(int? metaDataId, string name, string value)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new GetMetaDataExecResult(new Exception("No active session."));
            try
            {
                MetaData[] md = service.GetMetaData(token, metaDataId, name, value);
                return new GetMetaDataExecResult(md);
            }
            catch (Exception ex)
            {
                return new GetMetaDataExecResult(ex);
            }
        }

        ICreateMetaDataExecResult IFileManagement.CreateMetaData(string name, string value)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new CreateMetaDataExecResult(new Exception("No action session."));
            try
            {
                int metaDataId = service.CreateMetaData(token, name, value);
                return new CreateMetaDataExecResult(metaDataId);
            }
            catch (Exception ex)
            {
                return new CreateMetaDataExecResult(ex);
            }
        }

        #endregion

        #region IFileManagement Events

        EventHandler<FileUploadMessageArgs> onUploadComplete;
        event EventHandler<FileUploadMessageArgs> IFileManagement.OnUploadComplete
        {
            add { onUploadComplete += value; }
            remove { onUploadComplete -= value; }
        }

        EventHandler<FileUploadMessageArgs> onUploadStopped;
        event EventHandler<FileUploadMessageArgs> IFileManagement.OnUploadStopped
        {
            add { onUploadStopped += value; }
            remove { onUploadStopped += value; }
        }

        EventHandler<FileUploadMessageArgs> onUploadError;
        event EventHandler<FileUploadMessageArgs> IFileManagement.OnUploadError
        {
            add { onUploadError += value; }
            remove { onUploadError += value; }
        }

        EventHandler<FileUploadMessageArgs> onNewMessage;
        event EventHandler<FileUploadMessageArgs> IFileManagement.OnNewMessage
        {
            add { onNewMessage += value; }
            remove { onNewMessage -= value; }
        }

        EventHandler<FileUploadMessageArgs> onTotalUploadComplete;
        event EventHandler<FileUploadMessageArgs> IFileManagement.OnTotalUploadComplete
        {
            add { onTotalUploadComplete += value; }
            remove { onTotalUploadComplete -= value; }
        }


        int IFileManagement.ChunkSize
        {
            get
            {
                return chunkSize;
            }
            set
            {
                chunkSize = value;
            }
        }

        #endregion

        #region Uploading


        ICreateFileExecResult IFileManagement.CreateFile(string fileName)
        {
            return (this as IFileManagement).CreateFile(fileName, string.Empty, string.Empty);
        }

        ICreateFileExecResult IFileManagement.CreateFile(string fileName, string encoding, string callbackAddress)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new CreateFileExecResult(new Exception("No active session."));

            if (transfer == null)
                transfer = new DiomedeStorageTransferClient();
            try
            {
                long fileID = transfer.CreateFile(token, Path.GetFileName(fileName), callbackAddress, "");
                return new CreateFileExecResult(fileID);
            }
            catch (Exception ex)
            {
                return new CreateFileExecResult(ex);
            }
        }

        IUploadExecResult IFileManagement.Upload(string fileName)
        {
            return (this as IFileManagement).Upload(fileName, string.Empty, string.Empty);
        }

        IUploadExecResult IFileManagement.Upload(string fileName, string encoding, string callback)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new UploadExecResult(new Exception("No active session."));

            if (transfer == null)
                transfer = new DiomedeStorageTransferClient();
            try
            {
                using (FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read))
                {
                    UploadWithCreateFileInfo fileInfo = new UploadWithCreateFileInfo();
                    fileInfo.callbackAddress = callback;
                    fileInfo.fileName = Path.GetFileName(fileName);
                    fileInfo.totalLength = (int?) stream.Length;
                    fileInfo.hash = string.Empty;
                    long fileID = transfer.UploadWithCreateFile(token, fileInfo, stream);
                    stream.Close();
                    return new UploadExecResult(fileID);
                }
            }
            catch (Exception ex)
            {
                return new UploadExecResult(ex);
            }
        }

        IUploadExecResult IFileManagement.Upload(string fileName, long offset, long length)
        {
            return (this as IFileManagement).Upload(fileName, offset, length, string.Empty, string.Empty);
        }

        IUploadExecResult IFileManagement.Upload(string fileName, long offset, long length, string encoding, string callbackAddress)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new UploadExecResult(new Exception("No active session."));

            if (transfer == null)
                transfer = new DiomedeStorageTransferClient();
            try
            {
                long fileID = transfer.CreateFile(token, Path.GetFileName(fileName), callbackAddress, string.Empty);
                FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read);
                stream.Seek(offset, SeekOrigin.Begin);
                byte[] buffer = new byte[length];
                stream.Read(buffer, 0, (int)length);

                UploadInfo fileInfo = new UploadInfo();
                fileInfo.fileID = fileID;
                fileInfo.bufferLength = (int?) length;
                fileInfo.offset = offset;
                fileInfo.isComplete = false;
                transfer.Upload(token, fileInfo, stream);
                return new UploadExecResult(fileID);
            }
            catch(Exception ex)
            {
                return new UploadExecResult(ex);
            }
        }

        IUploadExecResult IFileManagement.Upload(long fileID, Stream stream, long offset, bool isComplete)
        {
            return (this as IFileManagement).Upload(fileID, stream, offset, isComplete, string.Empty, string.Empty);
        }

        IUploadExecResult IFileManagement.Upload(long fileID, Stream stream, long offset, bool isComplete, string encoding, string callbackAddress)
        {
            if (service == null || string.IsNullOrEmpty((this as ISession).Token))
                return new UploadExecResult(new Exception("No active session."));

            if (transfer == null)
                transfer = new DiomedeStorageTransferClient();

            try
            {
                long length = stream.Length;

                UploadInfo fileInfo = new UploadInfo();
                fileInfo.fileID = fileID;
                fileInfo.bufferLength = (int?)length;
                fileInfo.offset = offset;
                fileInfo.isComplete = isComplete;
                transfer.Upload(token, fileInfo, stream);
                transfer.Upload(token, fileInfo, stream);
                return new UploadExecResult(fileID);
            }
            catch (Exception ex)
            {
                return new UploadExecResult(ex);
            }
        }

        #endregion

    }
    #endregion
}